# -*- coding: utf-8 -*-  
'''
关系相关工具类

Created on 2021年10月2日
@author: luoyi
'''
import threading
import json

import utils.conf as conf


#    关系类
class Relationship:
    _INSTANCE_LOCK = threading.Lock()
    
    @classmethod
    def instance(cls, *args, **kwargs):
        if (not hasattr(Relationship, '_instance')):
            with Relationship._INSTANCE_LOCK:
                if (not hasattr(Relationship, '_instance')):
                    Relationship._instance = Relationship(*args, **kwargs)
                    pass
                pass
            pass
        return Relationship._instance
    
    def __init__(self, question_schemas_path=conf.DATASET_BAIDU.get_question_schemas_path()):
        self._question_schemas_path = question_schemas_path
        
        self._rel2id = {}
        self._sot2id = {}
        pass
    
    #    从文件加载
    def load_from_file(self):
        #    关系名
        rel_set = set()
        #    subject_type名
        subject_type_set = set()
        #    object_type名
        object_type_set = set()
        
        with open(file=self._question_schemas_path, mode='r', encoding='utf-8') as fr:
            line = fr.readline()
            
            while (line is not None):
                line = line.strip().replace('\n', '')
                if (len(line) == 0): break
                
                j = json.loads(line)
                
                rel_set.add(j['predicate'])
                subject_type_set.add(j['subject_type'])
                object_type_set.add(j['object_type'])
                
                line = fr.readline()
                pass
            pass
        
        #    关系名转为关系id
        rel2id = {}
        for rel in rel_set: rel2id[rel] = len(rel2id)
        self._rel2id = rel2id
        self._id2rel = {v:k for k,v in rel2id.items()}
        
        #    subject词性转为id，从1开始，0位给[PAD]
        sot2id = {'[PAD]':0, '[CLS]':1, '[SEP]':2, '[UNK]':3, '[MASK]':4, '[EOS]':5}
        for st in subject_type_set:
            k = 'subject-' + st
            if (sot2id.get(k) is not None): continue
            sot2id['B-' + k] = len(sot2id)
            sot2id['I-' + k] = len(sot2id)
            pass
        
        for ot in object_type_set:
            k = 'object-' + ot
            if (sot2id.get(k) is not None): continue
            sot2id['B-' + k] = len(sot2id)
            sot2id['I-' + k] = len(sot2id)
            pass
        self._sot2id = sot2id
        self._id2sot = {v:k for k,v in sot2id.items()}
        pass
    
    #    关系 <-> id
    def rel_to_id(self, rel):
        return self._rel2id.get(rel)
    def id_to_rel(self, rid):
        return self._id2rel.get(rid)
    def rel_size(self):
        return len(self._rel2id)
    
    #    subject 词 <-> id
    def st_to_id(self, word, st):
        return [self._sot2id.get('B-subject-' + st) if i == 0 else self._sot2id.get('I-subject-' + st) for i,_ in enumerate(word)]
    #    object 词 <-> id
    def ot_to_id(self, word, ot):
        return [self._sot2id.get('B-object-' + ot) if i == 0 else self._sot2id.get('I-object-' + ot) for i,_ in enumerate(word)]
    def id_to_sot(self, ids):
        return [self._id2sot.get(i) for i in ids]
    def sot_size(self):
        return len(self._sot2id)
    
    
    pass


